﻿/**
<code>
  <author name="Zealic" email="zealic(at)gmail.com" type="Creator"/>
</code>
**/
using System;
using System.IO;


namespace Zealib.Extensions
{
    /// <summary>
    /// Extensions for <seealso cref="System.IO.BinaryReader"/> class.
    /// </summary>
    public static class BinaryReaderExtensions
    {
        public static short ReadInt16(this BinaryReader self, EndianOrder order)
        {
            self.IsNotNull();
            if (BitConverter.IsLittleEndian && 
                (order == EndianOrder.LittleEndian))
            {
                return self.ReadInt16();
            }
            byte[] buffer = self.ReadBytes(sizeof(short));
            Array.Reverse(buffer);
            return BitConverter.ToInt16(buffer, 0);
        }

        public static ushort ReadUInt16(this BinaryReader self, EndianOrder order)
        {
            self.IsNotNull();
            if (BitConverter.IsLittleEndian && 
                (order == EndianOrder.LittleEndian))
            {
                return self.ReadUInt16();
            }
            byte[] buffer = self.ReadBytes(sizeof(ushort));
            Array.Reverse(buffer);
            return BitConverter.ToUInt16(buffer, 0);
        }

        public static int ReadInt32(this BinaryReader self, EndianOrder order)
        {
            self.IsNotNull();
            if (BitConverter.IsLittleEndian && 
                (order == EndianOrder.LittleEndian))
            {
                return self.ReadInt32();
            }
            byte[] buffer = self.ReadBytes(sizeof(int));
            Array.Reverse(buffer);
            return BitConverter.ToInt32(buffer, 0);
        }

        public static uint ReadUInt32(this BinaryReader self, EndianOrder order)
        {
            self.IsNotNull();
            if (BitConverter.IsLittleEndian && 
                (order == EndianOrder.LittleEndian))
            {
                return self.ReadUInt32();
            }
            byte[] buffer = self.ReadBytes(sizeof(uint));
            Array.Reverse(buffer);
            return BitConverter.ToUInt32(buffer, 0);
        }

        public static long ReadInt64(this BinaryReader self, EndianOrder order)
        {
            self.IsNotNull();
            if (BitConverter.IsLittleEndian && 
                (order == EndianOrder.LittleEndian))
            {
                return self.ReadInt64();
            }
            byte[] buffer = self.ReadBytes(sizeof(long));
            Array.Reverse(buffer);
            return BitConverter.ToInt64(buffer, 0);
        }

        public static ulong ReadUInt64(this BinaryReader self, EndianOrder order)
        {
            self.IsNotNull();
            if (BitConverter.IsLittleEndian && (order == EndianOrder.LittleEndian))
            {
                return self.ReadUInt64();
            }
            byte[] buffer = self.ReadBytes(sizeof(ulong));
            Array.Reverse(buffer);
            return BitConverter.ToUInt64(buffer, 0);
        }

        public static float ReadSingle(this BinaryReader self, EndianOrder order)
        {
            self.IsNotNull();
            if (BitConverter.IsLittleEndian && 
                (order == EndianOrder.LittleEndian))
            {
                return self.ReadSingle();
            }
            byte[] buffer = self.ReadBytes(sizeof(float));
            Array.Reverse(buffer);
            return BitConverter.ToSingle(buffer, 0);
        }

        public static double ReadDouble(this BinaryReader self, EndianOrder order)
        {
            self.IsNotNull();
            if (BitConverter.IsLittleEndian && 
                (order == EndianOrder.LittleEndian))
            {
                return self.ReadDouble();
            }
            byte[] buffer = self.ReadBytes(sizeof(double));
            Array.Reverse(buffer);
            return BitConverter.ToDouble(buffer, 0);
        }

        public static decimal ReadDecimal(this BinaryReader self, EndianOrder order)
        {
            self.IsNotNull();
            if (BitConverter.IsLittleEndian && (order == EndianOrder.LittleEndian))
            {
                return self.ReadDecimal();
            }
            byte[] buffer = self.ReadBytes(sizeof(decimal));
            Array.Reverse(buffer);
            return DecimalExtensions.ToDecimal(buffer, 0);
        }

    }
}
